<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * 作用域：变量的生效范围，是有限的
    *   全局作用域：ES5
    *       直接写在最外面（紧挨着script标签）的变量 拥有的作用域是全局作用域
    *       任何地方都可以访问的，就是全局 例如：
    * let a = 3//这是全局声明的3 任何位置都可以访问
    * function foo(){
    *   console.log(a)
    * }
    * foo()//打印3
    *
    * 但是如果：
    * let a = 3
    * function foo(){
    *   let a = 2//函数作用域的变量
    *   console.log(a)
    * }
    * foo()//打印2
    *
    *
    *   函数作用域：ES5
    *       函数内部声明的变量 就会在函数内部生效 优先于全局 函数所接收的形参拥有的是函数作用域
    *       函数传参永远是值传递，传递的是参数或者变量的值，而不是引用变量，引用时对象才具有引用关系
    *
    *   块级作用域：ES6
    *
    *
    * 变量访问的时候，从内到外，内部没有才去外部
    *
    * 例如：
    * let a = 3
    * function foo(){//会先在函数内部找有没有声明变量a，虽然声明了，但是是let声明的，let之前会有暂时性死区，所以访问就会报错
    *   console.log(a)
    *
    *
    *
    *   let a
    * }
    * foo()
    *
    * 再如：
    * let a = 3
    * function foo(){
    *   a = 2 //虽然函数内部并没有声明变量a 所以去函数外部寻找 所以这个 a=2 是修改外面全局的 let a=3 的值
    *   console.log(a)
    * }
    * foo()//打印出函数内修改后的a=2
    * console.log(a)//因为全局的a已经被修改过了，所以打印的也是2
    *
    * 再比如：
    * let a = 3
    * function foo(a){//形参相当于在函数内部声明变量 函数内部访问的时候就一定会访问内部的a 等价于写了let a = 实参传入的值
    *   a = 2//虽然实参没有传值，a一开始值等于undefined，但是现在 a = 2 将a的值改成了2
    *   console.log(a)//所以此时打印出a等于2
    * }
    * foo()
    * console.log(a)//我们从头到尾都没有动过全局的a 所以这里全局的a依旧是3
    *
    * 再比如：
    * let a = 3
    * function foo(a){//此时这里的形参a的值就是3，并不是全局的a，而是全局的a的值3传递给了后面foo(a)中的实参a，再由实参a将值3传递给形参a
    *   a = 2//然后再把a的值改成2 改的是函数内的形参a 而不是全局中的变量a 所以外面的全局变量a的值并没有变
    *   console.log(a)
    * }
    * foo(a)//()里面写的是啥？ 表达式 有返回值 这里返回的a的值是3 传递的是值 也就是3 所以此处a传递的是全局的变量a的值！也就是把3传了进去 等价于foo(3)
    * console.log(a)
    *
    * */


    /*
    *
    * 值类型：
    *   数值 字符串 布尔 undefined null
    * 如：
    * let a = 3 学霸a写的作业答案是3
    * let b = a 学渣b的作业抄了学霸a的作业的答案3
    * a = 4 学霸后来又把作业答案改成了4
    * console.log(b)//传递的是值 所以打印3 抄的是作业答案而不是直接拿了学霸a的作业
    *
    *
    * 引用类型：对象是引用类型
    *
    *   对象的存储空间：
    *       内存中：
    *       栈：存储具体的值，普通的数据类型，任何的赋值操作都是抄作业，当时赋值的是啥后面就是啥
    *       堆：只会保留索引，对象不是抄作业，对象是记录地址
    *
    * 对象的引用类型：
    * let aQianBao ={ //有一个钱包，名字叫做阿飞的钱包
    *   name:"阿飞"
    * }
    * let bQianBao = aQianBao //此时，银时拿到了这个钱包
    * bQianBao.name = "银时" //并且把这个钱包的名字改成了银时的钱包
    * console.log(aQianBao) //打印这个钱包的名字 从头到尾就只出现了这一个钱包
    *
    * 再如：
    * let a = { //创建了一个变量a，变量a指向一个对象，对象名字叫做阿飞
    *   name:"阿飞"
    * }
    * let b = a // 变量b引用了变量a指向的对象，相当于a和b同时指向了同一个对象
    * a = { //又重新创建了一个对象，变量a指向这个新对象 对象名字还叫做阿飞，但是这个对象阿飞 和之前 对象的阿飞 不是同一个 相当于a重新指向了这个新对象 但是之前b的指向并没有变
    *   name:"阿飞"
    * }
    * b.name = "银时" //变量b所指向的对象现在改名成银时
    *console.log(a,b) //所以现在有两个对象 一个是变量a所指向的对象阿飞 一个是变量b所指向的对象银时
    *
    *
    * 再比如：
    * let a = { //变量a指向第一个对象 这个对象名字叫做阿飞
    *   name:"阿飞"
    * }
    * a = { //变量a重新指向了一个新的对象 新的对象的名字还叫做阿飞
    *   name:"阿飞"
    * }
    * let b = a //变量b引用了变量a指向的新对象
    * b.name = "银时" // 并且把指向的新对象的名字改成了银时
    *
    * console.log(a,b) //所以此时变量a和变量b所指向的都是同一个对象 名字叫做银时 原来的第一个对象阿飞并没有人去指向它或者引用它
    *
    *
    * */




</script>
</body>
</html>